package com.qingxin.sys.dao;

import java.util.HashSet;
import java.util.Set;

/**
 * 更新数据库包装类
 * 
 * 提供三种更新模式：MAX, MIN, MIDDLE
 * MID：默认，除了null外都更新，exclude和include除外。<br>
 * MAX：最大模式，所有字段都更新，exclude除外。<br>
 * MIN：最小模式，仅更新include包含的字段。<br>
 */
public class Updater<T> {
	/**
	 * 实体类对象
	 */
	private T entity;

	/**
	 * 需要更新的字段，配合MIN、MID模式使用
	 */
	private Set<String> includes = new HashSet<String>();

	/**
	 * 不更新的字段，配合MID、MAX字段使用
	 */
	private Set<String> excludes = new HashSet<String>();

	/**
	 * 更新模式
	 */
	private UpdateMode mode = UpdateMode.MID;

	
	/**
	 * 更新模式枚举
	 */
	public static enum UpdateMode {
		MAX, MIN, MID
	}
	
	
	public Updater(T entity) {
		this.entity = entity;
	}

	
	public Updater(T entity, UpdateMode mode) {
		this.entity = entity;
		this.mode = mode;
	}
	
	
	/**
	 * 更新指定字段
	 * @param entity
	 * @param fields 要更新的字段
	 */
	public Updater(T entity, String fields) {
		this.entity = entity;
		this.mode = UpdateMode.MID;
		include(fields);
	}
	

	/**
	 * 设置更新模式
	 * @param mode
	 */
	public void setUpdateMode(UpdateMode mode) {
		this.mode = mode;
	}

	/**
	 * 设置需要更新的字段
	 * 
	 * @param fields 字段名称，多个字段以半角逗号分割
	 */
	public void include(String fields) {
		if(fields.indexOf(',')==-1){
			includes.add(fields);
		}else {
			String[] fieldArr = fields.split(",");
			for(String field : fieldArr){
				if(field.trim().length()>0){
					includes.add(field.trim());
				}
			}
		}
	}

	/**
	 * 设置不更新的字段
	 * 
	 * @param fields 字段名称，多个字段以半角逗号分割
	 */
	public void exclude(String fields) {
		if(fields.indexOf(',')==-1){
			excludes.add(fields);
		}else {
			String[] fieldArr = fields.split(",");
			for(String field : fieldArr){
				if(field.trim().length()>0){
					excludes.add(field.trim());
				}
			}
		}
	}

	
	/**
	 * 某一字段是否更新
	 * @param name
	 * @param value
	 * @return
	 */
	public boolean isUpdate(String name, Object value) {
		if (mode == UpdateMode.MAX) {
			return !excludes.contains(name);
			
		}else if (mode == UpdateMode.MIN) {
			return includes.contains(name);
			
		} else {
			if (value != null) {
				return !excludes.contains(name);
			} else {
				return includes.contains(name);
			}
		}
	}

	

	public T getEntity() {
		return entity;
	}

	public Set<String> getExcludes() {
		return excludes;
	}

	public Set<String> getIncludes() {
		return includes;
	}
	
}
